Skip to content

Add Xilinx Zynq-7000 (ZC702) wolfBoot port#770

Open
dgarske wants to merge 1 commit into
wolfSSL:masterfrom
dgarske:zynq7000
Open

Add Xilinx Zynq-7000 (ZC702) wolfBoot port#770
dgarske wants to merge 1 commit into
wolfSSL:masterfrom
dgarske:zynq7000

Conversation

@dgarske
Copy link
Copy Markdown
Member

@dgarske dgarske commented May 2, 2026

Summary

This PR adds an upstream wolfBoot port for the AMD/Xilinx Zynq-7000 SoC (Cortex-A9, ARMv7-A), verified end-to-end on the ZC702 Evaluation Kit. The port covers QSPI cold-boot, SD-card cold-boot, JTAG-loaded development, and signed Linux / U-Boot / bare-metal payload chain-loading from a single TARGET=zynq7000 build target.

It also generalises the existing ARMv7-A startup file so SAMA5D3 (Cortex-A5) and Zynq-7000 (Cortex-A9) now share one path through src/boot_arm32_start.S and src/boot_arm32.c.

A late simplification removes the LINUX_PAYLOAD=1 config knob that earlier revisions of this PR required, and hardens the legacy U-Boot uImage header detection with a CRC32 check. The result is a single config that "just works" for both bare-metal and Linux payloads, with no per-deployment switch.

What's in the port

New files

  • hal/zynq7000.c, hal/zynq7000.h, hal/zynq7000.ld -- HAL: UART, GPTimer, QSPI (XQspiPs N25Q128), Arasan v2.0 SDHCI hooks, cache teardown.
  • config/examples/zynq7000.config -- QSPI deployment (BootROM -> FSBL -> wolfBoot -> kernel/app).
  • config/examples/zynq7000_sdcard.config -- SD-card deployment with MBR layout that the Zynq-7000 BootROM accepts (FAT32-LBA + Active flag in p1).
  • test-app/app_zynq7000.c, test-app/ARM-zynq7000.ld -- bare-metal banner + heartbeat for end-to-end verification.
  • tools/scripts/zynq7000/* -- prepare_linux.sh, prepare_sdcard.sh, jtag_load.tcl, zynq7000_qspi.bif.
  • docs/Targets.md -- ZC702 bring-up walkthrough, QSPI / SD / JTAG paths, Linux recipe, ZynqMP comparison.

Touched

  • src/boot_arm32.c -- always emits the ARM Linux boot ABI when MMU=1 (r0=0, r1=~0, r2=DTB, r3=0). Bare-metal payloads ignore r0..r3, so one ABI covers both payload types. No more per-target LINUX_PAYLOAD switch needed.
  • src/boot_arm32_start.S -- generalised ARMv7-A startup (VBAR, per-mode stacks, cache invalidate, async-abort enable). Replaces what was a Cortex-A5-specific file; SAMA5D3 now uses the same path.
  • src/update_ram.c -- legacy U-Boot uImage header detection now validates magic + header CRC32 + payload size, dropping the joint false-positive probability from ~2^-32 to ~2^-64 and matching U-Boot's own mkimage/bootm validation. Reuses gpt_crc32_* from src/gpt.c.
  • arch.mk -- new CORTEX_A9=1 block under TARGET=zynq7000. WOLFBOOT_UBOOT_LEGACY is now always-on for zynq7000 (matching sibling ZynqMP / Versal targets); the previous LINUX_PAYLOAD=1 gate is gone. src/gpt.o is now linked for every Cortex-A9 build and every AARCH64 RAM-update build (where the hardened uImage check uses it).

Three boot paths, one config flavour

The QSPI config is the primary path. MMU=1 ELF=1 are baked in by default so the same wolfBoot image can chain-load a signed bare-metal .bin, a signed U-Boot, or a signed Linux zImage. Bare-metal payloads ignore the ARM Linux ABI registers wolfBoot passes in. Cost vs. a strictly bare-metal build is about 5 KB of unused FDT/MMU code (31 KB -> 36 KB).

For SD-card boot the layout is pure MBR (FAT32-LBA + Active in p1 for BOOT.BIN; raw Linux partitions p2/p3 for signed BOOT_A / BOOT_B). The BootROM (UG821 ch.6.3) refuses the GPT layout used on ZynqMP / Versal. src/disk.c's MBR-fallback handles this.

For Linux from SD we default to CONFIG_ARM_APPENDED_DTB (DTB concatenated to zImage and signed as one image), since the ARMv7 zImage decompressor on this kernel/load combo does not always preserve r2 across the transition to decompressed head.S. The raw-DTB-from-partition path via PART_DTS_BOOT remains plumbed for kernels that handle r2 correctly.

Booting Linux through wolfBoot

Verified end-to-end with stock Xilinx Linux 6.1.70 (xilinx_zynq_defconfig) and zynq-zc702.dtb. wolfBoot reads the signed kernel out of QSPI / SD, verifies it, copies it to DDR at 0x10000000, disables MMU and caches, and bx's into the zImage decompressor. Linux brings up both Cortex-A9 cores, the L2C-310, and the full SMP init; it panics only when no rootfs is supplied (expected for the proof-of-concept).

Hardened legacy uImage detection

The wolfBoot legacy uImage strip (WOLFBOOT_UBOOT_LEGACY in src/update_ram.c) previously matched on magic only -- one 32-bit comparison against UBOOT_IMG_HDR_MAGIC. That left a ~1-in-2^32 false-positive window for non-uImage payloads whose first 4 bytes happened to collide with the magic.

This PR replaces the magic-only check with a structural validator that requires all of:

  • ih_magic == 0x27051956
  • ih_size (big-endian) is > 0 and fits inside the signed image (<= total - 64)
  • ih_hcrc matches the CRC32 of the 64-byte header with the hcrc field treated as zero -- same algorithm (reflected CRC-32, poly 0xEDB88320) and same field semantics that U-Boot's mkimage / bootm use

Joint collision probability drops from ~2^-32 to ~2^-64. The CRC32 implementation is the existing gpt_crc32_* helpers in src/gpt.c, so no new code is added beyond the validator itself.

The hardening covers all targets that enable WOLFBOOT_UBOOT_LEGACY: zynq7000 (this PR), ZynqMP, and Versal.

Build verification

All four affected configurations build cleanly with no warnings or errors:

Config Arch Path text
zynq7000.config (QSPI) ARM32 RAM update 36888
zynq7000_sdcard.config ARM32 Disk update 41992
zynqmp.config AARCH64 RAM update 60288
sama5d3.config ARM32 RAM update (non-MMU) (unchanged)

The SAMA5D3 regression confirms the non-MMU branch of the generalised do_boot (used by targets without MMU=1) is unaffected by the always-Linux-ABI change.

Known limitations / follow-ups

  • ARMv7 zImage r2 quirk -- the appended-DTB path is the documented default. The raw-DTB-from-partition path works for decompressors that preserve r2; needs upstream Linux investigation before we can recommend it generally.
  • SDHCI v2.0 6 MHz cap -- src/sdhci.c needs an explicit DAT-line reset between transfers before we can raise the post-init clock. Sufficient for boot-time loading today (~3 MB/s).
  • L2 (PL310) -- not touched by wolfBoot; stock ZC702 FSBLs don't enable it. If a custom FSBL does, extend hal_prepare_boot() with an L2x0 clean-invalidate + disable.

Why a separate port from ZynqMP?

Despite the shared name, the two SoCs differ in nearly every block wolfBoot interacts with:

Aspect ZynqMP (hal/zynq.c) Zynq-7000 (hal/zynq7000.c)
CPU Cortex-A53 quad, AArch64 Cortex-A9 dual, ARMv7-A 32-bit
QSPI controller GQSPI (XQspiPsu) Linear/Static QSPI (XQspiPs)
SDHCI Arasan v3.0 + Cadence shim Arasan v2.0 + Cadence shim
Boot chain FSBL + PMUFW + BL31 + wolfBoot FSBL + wolfBoot
Linux entry EL2 (hypervisor mode) SVC (no exception levels)
Crypto HW CSU (AES-GCM, SHA3, PUF) none (DevC AES only)
bootgen -arch zynqmp zynq

With this PR the entire AMD/Xilinx adaptive-SoC lineup -- Zynq-7000, ZynqMP, Versal -- builds from a common wolfBoot codebase.

@dgarske dgarske self-assigned this May 2, 2026
Copilot AI review requested due to automatic review settings May 2, 2026 01:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an initial wolfBoot port for Xilinx Zynq-7000 on the ZC702 board, extending the codebase with a new ARMv7-A / Cortex-A9 target that boots via the Xilinx FSBL, verifies images from QSPI, and chain-loads a staged payload from DDR.

Changes:

  • Adds a new zynq7000 target across the HAL, startup code, linker scripts, and build system for FSBL-loaded Cortex-A9 boot.
  • Introduces a Zynq-7000 QSPI/UART HAL, RAM-boot configuration, and a minimal test application for bring-up validation.
  • Documents the target, JTAG workflow, QSPI layout, and adds helper scripts for XSDB/bootgen usage.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tools/scripts/zc702/zc702_qspi.bif Adds a bootgen BIF template for packaging FSBL + wolfBoot into BOOT.BIN.
tools/scripts/zc702/jtag_load.tcl Adds an XSDB script for JTAG bring-up by running FSBL and loading wolfboot.elf into DDR.
test-app/app_zynq7000.c Adds a minimal bare-metal ZC702 test app that prints a boot banner and heartbeat on UART1.
test-app/Makefile Wires the new target into test-app builds with the ARM32 startup object and target linker script.
test-app/ARM-zynq7000.ld Adds the linker script for the staged Zynq-7000 test application in DDR.
src/boot_zynq7000_start.S Adds Zynq-7000-specific ARMv7-A startup, vector setup, stack initialization, and early CPU state handling.
src/boot_arm32.c Adjusts ARM32 inline assembly immediate syntax used during chain-load handoff.
hal/zynq7000.ld Adds the wolfBoot linker script for execution from DDR at the FSBL handoff address.
hal/zynq7000.h Defines Zynq-7000 register maps and bitfields for UART, QSPI, and related peripherals.
hal/zynq7000.c Implements the new Zynq-7000 HAL, including UART, QSPI external flash access, and boot-preparation logic.
docs/Targets.md Documents the new ZC702 target, configuration, memory map, JTAG flow, and expected output.
config/examples/zynq7000.config Adds an example configuration for ECC256/SHA256 RAM-boot from external QSPI flash.
arch.mk Adds target selection and Cortex-A9-specific compiler/object settings for zynq7000.
Makefile Includes the new target in the default main build outputs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hal/zynq7000.c Outdated
@dgarske dgarske marked this pull request as ready for review May 6, 2026 22:08
@dgarske dgarske requested a review from Copilot May 6, 2026 22:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 9 comments.

Comment thread hal/zynq7000.c Outdated
Comment thread hal/zynq7000.c Outdated
Comment thread arch.mk Outdated
Comment thread arch.mk Outdated
Comment thread docs/Targets.md Outdated
Comment thread config/examples/zc702_sdcard.config Outdated
Comment thread tools/scripts/zc702/prepare_sdcard.sh Outdated
Comment thread tools/scripts/zc702/prepare_linux.sh Outdated
Comment thread test-app/app_zynq7000.c Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 8 comments.

Comment thread arch.mk Outdated
Comment thread test-app/ARM-zynq7000.ld Outdated
Comment thread src/boot_arm32.c Outdated
Comment thread tools/scripts/zynq7000/jtag_load.tcl
Comment thread tools/scripts/zc702/prepare_sdcard.sh Outdated
Comment thread tools/scripts/zc702/prepare_linux.sh Outdated
Comment thread docs/Targets.md Outdated
Comment thread docs/Targets.md Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 8 comments.

Comment thread test-app/Makefile
Comment thread hal/zynq7000.c Outdated
Comment thread hal/zynq7000.c
Comment thread hal/zynq7000.c
Comment thread hal/zynq7000.c
Comment thread hal/zynq7000.c
Comment thread config/examples/zynq7000_sdcard.config
Comment thread .github/workflows/test-configs.yml
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Comment thread src/boot_arm32_start.S
Comment thread hal/zynq7000.c
Comment thread docs/Targets.md Outdated
Comment thread config/examples/zynq7000_sdcard.config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants